﻿using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;


namespace Spore.SQL
{
    public class GrammarAnalyzer
    {
        //=========================================================================
        // 构造函数: 
        //   exp: 要分析的表达式
        //=========================================================================
        public GrammarAnalyzer(string exp)
        {
            expression = exp;
            index = 0;
            tokens = new List<Token>();
        }

        //=========================================================================
        // 表达式词法分析
        //=========================================================================
        public void Analyze()
        {
            tokens.Clear();
            index = 0;

            Token tok = null;
            while ((tok = GetToken()) != null)
            {
                tokens.Add(tok);
            }
        }

        //=========================================================================
        // 获取标记列表
        //=========================================================================
        public Token[] TokenList
        {
            get { return tokens.ToArray(); }
        }

        //=========================================================================
        // 分析后读取一个标记
        //=========================================================================
        private Token GetToken()
        {
            Token token = null;

            // 忽略空白字符
            while (HasChar && char.IsWhiteSpace(CurrentChar)) MoveNext();

            if (!HasChar) return null;

            if (CurrentChar == '(')             // 左括号
            {
                token = new LP();
                MoveNext();
            }
            else if (CurrentChar == ')')        // 右括号
            {
                token = new RP();
                MoveNext();
            }
            else
            {
                int start = index;
                int end;
                do
                {
                    end = index;
                    MoveNext();
                } while (HasChar && !IsStop(CurrentChar));

                string val = expression.Substring(start, end + 1 - start);
                if(IsOperator(val))
                {
                    token = new Oper(val);
                }
                else
                {
                    token = new Operand(val);
                }
            }
            return token;
        }

        private bool IsStop(char input)
        {
            return char.IsWhiteSpace(input) || input == ')' || input == '(';
        }

        private bool IsOperator(string val)
        {
            string pattern = "and|or|not";
            return Regex.IsMatch(val, pattern, RegexOptions.IgnoreCase);
        }

        //=========================================================================
        // 是否还有可读字符
        //=========================================================================
        private bool HasChar
        {
            get { return index < expression.Length; }
        }

        //=========================================================================
        // 当前字符
        //=========================================================================
        private char CurrentChar
        {
            get { return expression[index]; }
        }

        //=========================================================================
        // 转到下一字符
        //=========================================================================
        private void MoveNext()
        {
            ++index;
        }

        //=========================================================================
        // 转到上一字符
        //=========================================================================
        private void MovePrev()
        {
            --index;
        }

        private int index;
        private string expression;
        private List<Token> tokens;
    }
}
